#pragma once

#include "Log.hpp"
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>

class TcpClient
{
public:
    TcpClient(const std::string& ip, uint16_t port)
        : _ip(ip), _port(port), _sock(-1)
    { }

    // 客户端初始化
    void init()
    {
        // 创建socket文件描述符
        _sock = socket(AF_INET, SOCK_STREAM, 0);
        if(_sock < 0)   // 失败
        {
            logMessage(FATAL, "socket error, %d:%s\n", errno, strerror(errno));
            exit(2);
        }
        logMessage(NORMAL, "socket success, _sock:%d", _sock);

        // 客户端连接服务器
        struct sockaddr_in sock_srv;
        memset(&sock_srv, 0, sizeof(sock_srv));
        sock_srv.sin_family = AF_INET;
        sock_srv.sin_addr.s_addr = inet_addr(_ip.c_str());
        sock_srv.sin_port = htons(_port);
        socklen_t len = sizeof(sock_srv);

        if(connect(_sock, (struct sockaddr *)&sock_srv, len) < 0)
        {
            logMessage(FATAL, "connect fail, %d:%s\n", errno, strerror(errno));
            exit(3);
        }
        logMessage(NORMAL, "connect success\n");
    }

    void start()
    {
        std::string msg;   // 发送的数据
        char buffer[1024]; // 缓冲区，获取服务器发回数据

        while(true)
        {
            std::cout << "请输入你要发送的数据: " << std::flush;
            std::getline(std::cin, msg);   // 逐行读取

            if(msg == "quit") break;

            ssize_t n = send(_sock, (void*)msg.c_str(), msg.size(), 0);  // 发送数据
            if(n > 0)   // 成功发送数据
            {
                ssize_t s = recv(_sock, (void *)buffer, 1023, 0);
                if(s > 0)
                {
                    buffer[s] = '\0';
                    printf("回显# %s\n", buffer);
                }
            }
            else if(n == 0)
            {
                logMessage(DEBUG, "没有发送有效数据, n:%d", n);
                continue;
            }
            else
            {
                logMessage(ERROR, "数据发送失败!");
                continue;
            }
        }
    }
    
private:
    std::string _ip;   // 服务器ip
    uint16_t _port;    // 服务器对应进程的端口号
    int _sock;         // socket文件描述符
};